package com.wust.modules.poi.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.wust.modules.poi.excel.entity.params.MergeEntity;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

/**
 * @author wanheng
 */
public final class PoiMergeCellUtil {

    public static void mergeCells(Sheet sheet, Map<Integer, int[]> mergeMap, int startRow) {
        mergeCells(sheet, mergeMap, startRow, sheet.getLastRowNum());
    }

    public static void mergeCells(Sheet sheet, Map<Integer, int[]> mergeMap, int startRow, int endRow) {
        Map<Integer, MergeEntity> mergeDataMap = new HashMap();
        if (mergeMap.size() != 0) {
            Set<Integer> sets = mergeMap.keySet();

            label52:
            for(int i = startRow; i <= endRow; ++i) {
                Row row = sheet.getRow(i);
                Iterator iterator = sets.iterator();

                while(true) {
                    while(true) {
                        if (!iterator.hasNext()) {
                            continue label52;
                        }

                        Integer index = (Integer) iterator.next();
                        if (row != null && row.getCell(index) != null) {
                            String text = row.getCell(index).getStringCellValue();
                            if (StringUtils.isNotEmpty(text)) {
                                hanlderMergeCells(index, i, text, mergeDataMap, sheet, row.getCell(index), mergeMap.get(index));
                            } else {
                                mergeCellOrContinue(index, mergeDataMap, sheet);
                            }
                        } else if (mergeDataMap.get(index) != null && mergeDataMap.get(index).getEndRow() == 0) {
                            mergeDataMap.get(index).setEndRow(i - 1);
                        }
                    }
                }
            }

            if (mergeDataMap.size() > 0) {
                Iterator iterator = mergeDataMap.keySet().iterator();

                while(iterator.hasNext()) {
                    Integer index = (Integer) iterator.next();
                    sheet.addMergedRegion(new CellRangeAddress(mergeDataMap.get(index).getStartRow(), mergeDataMap.get(index).getEndRow(), index, index));
                }
            }

        }
    }

    private static void hanlderMergeCells(Integer index, int rowNum, String text, Map<Integer, MergeEntity> mergeDataMap, Sheet sheet, Cell cell, int[] delys) {
        if (mergeDataMap.containsKey(index)) {
            if (checkIsEqualByCellContents(mergeDataMap.get(index), text, cell, delys, rowNum)) {
                mergeDataMap.get(index).setEndRow(rowNum);
            } else {
                sheet.addMergedRegion(new CellRangeAddress(mergeDataMap.get(index).getStartRow(), mergeDataMap.get(index).getEndRow(), index, index));
                mergeDataMap.put(index, createMergeEntity(text, rowNum, cell, delys));
            }
        } else {
            mergeDataMap.put(index, createMergeEntity(text, rowNum, cell, delys));
        }

    }

    private static void mergeCellOrContinue(Integer index, Map<Integer, MergeEntity> mergeDataMap, Sheet sheet) {
        if (mergeDataMap.containsKey(index) && mergeDataMap.get(index).getEndRow() != mergeDataMap.get(index).getStartRow()) {
            sheet.addMergedRegion(new CellRangeAddress(mergeDataMap.get(index).getStartRow(), mergeDataMap.get(index).getEndRow(), index, index));
            mergeDataMap.remove(index);
        }

    }

    private static MergeEntity createMergeEntity(String text, int rowNum, Cell cell, int[] delys) {
        MergeEntity mergeEntity = new MergeEntity(text, rowNum, rowNum);
        if (delys != null && delys.length != 0) {
            List<String> list = new ArrayList(delys.length);
            mergeEntity.setRelyList(list);

            for(int i = 0; i < delys.length; ++i) {
                list.add(getCellNotNullText(cell, delys[i], rowNum));
            }
        }

        return mergeEntity;
    }

    private static boolean checkIsEqualByCellContents(MergeEntity mergeEntity, String text, Cell cell, int[] delys, int rowNum) {
        if (delys != null && delys.length != 0) {
            if (mergeEntity.getText().equals(text)) {
                for(int i = 0; i < delys.length; ++i) {
                    if (!getCellNotNullText(cell, delys[i], rowNum).equals(mergeEntity.getRelyList().get(i))) {
                        return false;
                    }
                }

                return true;
            } else {
                return false;
            }
        } else {
            return mergeEntity.getText().equals(text);
        }
    }

    private static String getCellNotNullText(Cell cell, int index, int rowNum) {
        Sheet sheet;
        String temp;
        for(temp = cell.getRow().getCell(index).getStringCellValue(); StringUtils.isEmpty(temp); temp = sheet.getRow(rowNum).getCell(index).getStringCellValue()) {
            sheet = cell.getRow().getSheet();
            --rowNum;
        }

        return temp;
    }
}
